home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 19 / Mac Magazin and MacEasy Magazine CD - Issue 19.iso / Musik & Kunst / Ear Workout 2.1 / source code / ear_calc.cp < prev    next >
Text File  |  1995-12-02  |  8KB  |  267 lines

  1. //    ear_calc.cp
  2. //    This file contains functions that do number-crunching (plus
  3. //    a few functions that do Unix-style I/O to files), but
  4. //    nothing specific to the Mac.
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <math.h>
  10.  
  11. double sin(),cos(),sqrt(),fabs();
  12. #define PI 3.141592653589793
  13.  
  14. #define NEED_MAC_STUFF 0
  15.  
  16. #include "ear_prototypes.h"
  17. #include "ear_defines.h"
  18.  
  19.  
  20.         /*
  21.         Returns a random number in [0,1).
  22.         */
  23.         double
  24. random_double()
  25.         {
  26.           long int n1,n2;
  27.           do {
  28.             n1 = Random();
  29.           }while(n1<-32766 || n1>32766);
  30.           do {
  31.             n2 = Random();
  32.           }while(n2<-32766 || n2>32766);
  33.           n1 += 32766;
  34.           n2 += 32766; /* both in range of 0 to 65532 */
  35.           n1 = n1 & 16383; /* avoid problems with sign */
  36.           return (n1*65533L+n2)/1.073758204e+09;
  37.         }
  38.  
  39.  
  40.         /* Before calling the following, you must do:
  41.              InitGraf(&thePort);
  42.            or else use the stdio routines. */
  43.     void
  44. init_random()
  45.         {
  46.           unsigned long t;
  47.           int i,n;
  48.           /* The following didn't work, same random numbers returned every time: */
  49.           /*
  50.           GetDateTime(&randSeed);
  51.           */
  52.           
  53.           /* A total kludge: */
  54.           GetDateTime(&t);
  55.           n = 1 + (t & 1023L);
  56.           for (i=1; i<=n; i++) {
  57.             Random();
  58.           }
  59.         }
  60.  
  61.     /* generate a random number from 1 to n */
  62.     int
  63. random_integer(int n)
  64.     {
  65.       int k;
  66.       do {
  67.         k = random_double()*n+1;
  68.       } while (k<1 || k>n);
  69.       return k;
  70.     }
  71.     
  72.         double
  73. small_integer_ratio()
  74.         {
  75.           double x,y;
  76.           x = small_integer();
  77.           y = small_integer();
  78.           return x/y;
  79.         }
  80.  
  81.     int
  82. small_integer()
  83.         {
  84.           int n;
  85.           n= 1;
  86.           while (random_double()<.25) {
  87.             ++n;
  88.           }
  89.           return n;
  90.         }
  91.         /*
  92.         The main problem here is that we only have an 8-bit DAC, so we have to
  93.         choose between distorting and making waveforms with amplitudes so small
  94.         that you can hear the granularity.  Waveforms are first normalized
  95.         to have unit rms amplitude.  Then they are transformed into 8-bit
  96.         integers via
  97.                 128+100*amplitude*waveform
  98.         where amplitude is an input parameter, and results outside the range of 0-254
  99.         result in clipping.
  100.         Global variable wave_table_size should be set by calling routine, unless
  101.         reading sample (kind=5).
  102.         Amplitude should typically be set to about 0.3 to avoid distortion
  103.         when summing the waveforms of four voices.
  104.         
  105.         modified 12 Mar 95 to renormalize just enough to avoid clipping
  106.         */
  107.     void
  108. make_wave_table(unsigned char *final_wave_table,    //-- storage for final result
  109.         double *temp_wave_table,        //-- temporary storage
  110.         int kind,
  111.         double amplitude,
  112.         int wave_table_size,
  113.         int make_temp_wave_table)
  114.         {
  115.           int i,garbage;
  116.           double x,s,max_value;
  117.           static double raw_ampl,avg;
  118.           if (make_temp_wave_table) {
  119.           
  120.           if (kind==5) {
  121.             FILE *f;
  122.             int z;
  123.             char line[MAX_STR_LEN];
  124.             f = fopen("wave_file","r");
  125.             if (f==(FILE *)0) {
  126.               bail_out("Error opening file for input\n");
  127.               exit(-1);
  128.             }
  129.             wave_table_size = 0;
  130.             fget_line(line,f);
  131.             garbage = atoi(line); // pitch offset
  132.             for (;;) {
  133.               z = fget_line(line,f);
  134.               if (z!=0) break;
  135.               temp_wave_table[wave_table_size++] = atoi(line);
  136.             }
  137.             fclose(f);
  138.           }
  139.           else {
  140.           for (i=0; i<wave_table_size; i++) {
  141.             switch(kind) {
  142.               /****** sine wave ******/
  143.               case 1:
  144.                 x = ((double ) i)/((double) wave_table_size);
  145.                 s = sin(2.*PI*x);
  146.                 temp_wave_table[i] = s;
  147.                 break;
  148.               /****** square wave ******/
  149.               case 2:
  150.                 if (i<wave_table_size/2)
  151.                   temp_wave_table[i] = 1.0;
  152.                 else
  153.                   temp_wave_table[i] = -1.0;
  154.                 break;
  155.               /****** square+sine wave ******/
  156.               case 3:
  157.                 if (i<wave_table_size/2)
  158.                   temp_wave_table[i] = 0.5;
  159.                 else
  160.                   temp_wave_table[i] = -0.5;
  161.                 x = ((double ) i)/((double) wave_table_size);
  162.                 s = sin(2.*PI*x);
  163.                 temp_wave_table[i] += 0.5*s;
  164.                 break;
  165.               /****** superimposed harmonics ******/
  166.               case 4:
  167.                 {
  168.                   int nharm,j;
  169.                   double fall_off,f,u;
  170.                   nharm = 10;
  171.                   fall_off = 0.9;
  172.                   if (nharm>20) {
  173.                     bail_out("Error constructing waveform - too many harmonics\n");
  174.                     exit(-1);
  175.                   }
  176.                   x = ((double ) i)/((double) wave_table_size);
  177.                   temp_wave_table[i] = 0.0;
  178.                   u = 2.*PI*x;
  179.                   f = 1.0;
  180.                   for (j=1; j<=nharm; j++) {
  181.                     s = sin(u*j);
  182.                     temp_wave_table[i] += f*s;
  183.                     f = f*fall_off;
  184.                   }
  185.                 }
  186.                 break;
  187.              } /* end case */
  188.            } /* end for */
  189.            } /* end else clause, i.e. not a sample */
  190.           /* normalize: */
  191.           raw_ampl = 0.0;
  192.           avg = 0.0;
  193.           for (i=0; i<wave_table_size; i++) {
  194.             double u;
  195.             u = temp_wave_table[i];
  196.             avg += u;
  197.             raw_ampl += u*u;
  198.           }
  199.           avg = avg/wave_table_size;
  200.           raw_ampl = raw_ampl/wave_table_size;
  201.           raw_ampl = sqrt(raw_ampl-avg*avg);
  202.           max_value = 0.0;
  203.           for (i=0; i<wave_table_size; i++) {
  204.             if (fabs(temp_wave_table[i]-avg)>max_value)
  205.               max_value = fabs(temp_wave_table[i]-avg);
  206.        }
  207.       if (amplitude*100*max_value/raw_ampl > 120.)
  208.         raw_ampl = raw_ampl * (amplitude*100*max_value/raw_ampl/120.);
  209.       
  210.       }//-- end if make_temp_wave_table
  211.       
  212.           for (i=0; i<wave_table_size; i++) {
  213.             double u;
  214.             u = 128 + amplitude * 100 * (temp_wave_table[i]-avg) / raw_ampl;
  215.             if (u>=254) u=254;
  216.             if (u<=0) u = 0;
  217.             final_wave_table[i] = u;
  218.           }
  219.         }
  220.  
  221.     int
  222. fget_line(char *line,FILE *f)
  223.     {
  224.       char *ret_val;
  225.           ret_val = fgets(line,MAX_STR_LEN-5,f);
  226.           if (ret_val==(char *) 0 || strlen(line)>MAX_STR_LEN-7) {
  227.         *line = '\0';
  228.         if (strlen(line)>MAX_STR_LEN-7)
  229.           fprintf(stderr,"*** error - line too long\n");
  230.         return 1;
  231.       }
  232.       if (line[strlen(line)-1]=='\n')
  233.         line[strlen(line)-1] = '\0';
  234.       return 0;
  235.     }
  236.  
  237.     void
  238. debug_print(char *message)
  239.     {
  240.       FILE *f;
  241.       static int created_file_already = 0;
  242.       if (!created_file_already)
  243.         f = fopen("errors","w");
  244.       else
  245.         f = fopen("errors","a");
  246.       if (f != (FILE *) 0) {
  247.         fprintf(f,"%s",message);
  248.         fflush(f);
  249.         fclose(f);
  250.         created_file_already = 1;
  251.       }
  252.     }
  253.     
  254.     double
  255. choose_duration(double typical_tempo)
  256.     {
  257.         double min_duration,tempo,d;
  258.         min_duration = .7 * 2000.*60./typical_tempo;
  259.             tempo = typical_tempo*(1.+.2*(random_double()+random_double()-1.));
  260.             d = 2000.*60./tempo;
  261.             while (d<min_duration) {
  262.               d *= 2;
  263.             }
  264.             return d;
  265.     }
  266.  
  267.